﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using NHibernate;
using NHibernateSample.Domain.Entities;

namespace NHibernateSample.DAL
{
    public class LazyLoading
    {
        protected ISession Session;

        public LazyLoading(ISession _session)
        {
            Session = _session;
        }

        #region LazyLoading
        #region 一对多关系
        /// <summary>
        /// 数据访问层中方法一：加载Customer对象
        /// </summary>
        /// <param name="customerId"></param>
        /// <returns></returns>
        public Customer LazyLoad(int customerId)
        {
            return Session.Get<Customer>(customerId);
        }

        /// <summary>
        /// 数据访问层中方法二：加载Customer对象并使用Using强制清理关闭Session
        /// </summary>
        /// <param name="customerId"></param>
        /// <returns></returns>
        public Customer LazyLoadUsingSession(int customerId)
        {
            using (ISession _session = new NHibernateHelper().GetSession())
            {
                return _session.Get<Customer>(customerId);
            }
        }
        #endregion

        #region 多对多关系
        public Order LazyLoadOrderAggregate(int orderId)
        {
            return Session.Get<Order>(orderId);
        }

        public Order LazyLoadOrderAggregateUsingSession(int orderId)
        {
            using (ISession _session = new NHibernateHelper().GetSession())
            {
                return _session.Get<Order>(orderId);
            }
        }
        #endregion
        #endregion

        #region 立即加载
        #region 一对多关系
        //1.使用lazy="false"属性
        //这里介绍第一种方法就是修改映射文件来立即加载，打开Customer.hbm.xml文件，在Set元素中添加lazy="false"。     
        
        /// <summary>
        /// 2.使用NHibernateUtil实用类
        /// NHibernate提供实用类(NHibernateUtil)不光光只是用来测试被关联的对象集合是否已初始化，还有一个非常重要的功能就是可以强制初始化未初始化的相关联的对象。
        /// </summary>
        /// <param name="customerId"></param>
        /// <returns></returns>
        public Customer EagerLoadUsingSessionAndNHibernateUtil(int customerId)
        {
            using (ISession _session = new NHibernateHelper().GetSession())
            {
                Customer customer = _session.Get<Customer>(customerId);
                NHibernateUtil.Initialize(customer.Orders);
                return customer;
            }
        }
        #endregion

        #region 多对多关系
        /// <summary>
        /// 2.使用NHibernateUtil实用类
        /// 如果你需要获得Order实体的相关联对象可以使用NHibernateUtil类初始化关联对象(把他们从数据库取出来)。
        /// </summary>
        /// <param name="customerId"></param>
        /// <returns></returns>
        public Order EagerLoadOrderAggregateSessionAndNHibernateUtil(int orderId)
        {
            using (ISession _session = new NHibernateHelper().GetSession())
            {
                Order order = _session.Get<Order>(orderId);
                NHibernateUtil.Initialize(order.Customer);
                NHibernateUtil.Initialize(order.Products);
                return order;
            }
        }        
        #endregion

        //3.使用HQL抓取策略
        public Order EagerLoadOrderAggregateWithHQL(int orderId)
        {
            using (ISession _session = new NHibernateHelper().GetSession())
            {
                return _session.CreateQuery("from Order o" +
                    " left outer join fetch o.Products" +
                    " inner join fetch o.Customer where o.OrderId=:orderId")
                    .SetInt32("orderId", orderId)
                    .UniqueResult<Order>();
            }
        }
        #endregion

    }
}
